package com.hzlj.position.locate.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fz.common.base.core.DistanceUtils;
import com.fz.common.base.dto.DeleteCommonDTO;
import com.fz.common.base.dto.PageParamDTO;
import com.fz.common.base.dto.QueryPageResultDTO;
import com.fz.common.base.exception.PubError;
import com.fz.common.base.exception.PubException;
import com.fz.common.dict.annotation.DictConvert;
import com.google.common.collect.Lists;
import com.hzlj.position.locate.common.dto.abnProhibitAreas.*;
import com.hzlj.position.locate.common.dto.abnProhibitAreasPosition.AbnProhibitAreasPositionAddDTO;
import com.hzlj.position.locate.common.model.AbnProhibitAreas;
import com.hzlj.position.locate.common.model.Position;
import com.hzlj.position.locate.cache.AbnProhibitAreasCache;
import com.hzlj.position.locate.converter.AbnProhibitAreasConverter;
import com.hzlj.position.locate.dao.AbnProhibitAreasDao;
import com.hzlj.position.locate.service.AbnProhibitAreasJzryService;
import com.hzlj.position.locate.service.AbnProhibitAreasPositionService;
import com.hzlj.position.locate.service.AbnProhibitAreasService;
import com.hzlj.sqjz.system.cache.XzqhBjCache;
import com.hzlj.sqjz.system.common.dto.xzqhBj.XzqhBjQueryResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.hzlj.position.config.config.IdConfig.POSITION_ID_GEN;

/**
 * 禁止区域(AbnProhibitAreas)表服务接口
 *
 * @author lifh
 * @date 2023-03-28 10:20:33
 */
@Slf4j
@Service
public class AbnProhibitAreasServiceImpl implements AbnProhibitAreasService {
    @Resource
    private AbnProhibitAreasDao abnProhibitAreasDao;
    @Resource
    private AbnProhibitAreasCache abnProhibitAreasCache;
    @Resource
    private XzqhBjCache xzqhBjCache;
    @Resource
    private AbnProhibitAreasJzryService abnProhibitAreasJzryService;
    @Resource
    private AbnProhibitAreasPositionService abnProhibitAreasPositionService;


    /**
     * 通过id查询单条数据
     *
     * @param id id
     * @return 实例对象
     */
    @Override
    public AbnProhibitAreasQueryResultDTO getAbnProhibitAreasById(String id) {
        AbnProhibitAreas abnProhibitAreas = this.abnProhibitAreasDao.getById(id);
        if (Objects.isNull(abnProhibitAreas)) {
            throw new PubException(PubError.NO_OBJECT_FOUND);
        }
        AbnProhibitAreasQueryResultDTO result = AbnProhibitAreasConverter.from(abnProhibitAreas);
        result.setJzry(
                abnProhibitAreasJzryService.listAbnProhibitAreasJzry(id)
        );
        return result;

    }


    /**
     * 新增数据
     *
     * @param dto 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAbnProhibitAreas(AbnProhibitAreasAddDTO dto) {
        AbnProhibitAreas abnProhibitAreas = AbnProhibitAreasConverter.from(dto);
        abnProhibitAreas.setId(POSITION_ID_GEN.nextIdStr());
        //新增数据
        this.abnProhibitAreasDao.save(abnProhibitAreas);
        //人员
        abnProhibitAreasJzryService.updateAbnProhibitAreasJzry(abnProhibitAreas.getId(), dto.getJzry());
        refresh();
        log.info("【新增数据成功】:abnProhibitAreas={}", abnProhibitAreas);
    }


    /**
     * 修改数据
     *
     * @param dto 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAbnProhibitAreas(AbnProhibitAreasUpdateDTO dto) {
        AbnProhibitAreas abnProhibitAreas = AbnProhibitAreasConverter.from(dto);
        boolean update = this.abnProhibitAreasDao.updateAbnProhibitAreas(abnProhibitAreas);
        if (update) {
            log.info("【更新数据成功】:abnProhibitAreas={}", abnProhibitAreas);
        }
        //人员
        abnProhibitAreasJzryService.updateAbnProhibitAreasJzry(abnProhibitAreas.getId(), dto.getJzry());
        refresh();
        return update;
    }

    /**
     * 删除数据
     *
     * @param dto 实例对象
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAbnProhibitAreas(DeleteCommonDTO<String> dto) {
        boolean result = this.abnProhibitAreasDao.deleteAbnProhibitAreas(dto);
        if (result) {
            log.info("【删除数据成功】:AbnProhibitAreas={}", dto);
        }
        refresh();
        return result;
    }

    @Override
    public void syncPositions(List<Position> positions) {
        //获取需要判定的人+区域
        Set<String> jzIds = positions.stream().map(Position::getJzId).collect(Collectors.toSet());
        Map<String, List<AbnProhibitAreasWithJzryDTO>> areasWithJzry = this.listAbnProhibitAreasWithJzry(jzIds);
        if (areasWithJzry == null) {
            return;
        }

        List<AbnProhibitAreasPositionAddDTO> adds = Lists.newArrayList();
        //判断是会否在区域里
        for (Position position : positions) {
            String jzId = position.getJzId();
            if (!areasWithJzry.containsKey(jzId)) {
                continue;
            }
            List<AbnProhibitAreasWithJzryDTO> jzries = areasWithJzry.get(jzId);
            for (AbnProhibitAreasWithJzryDTO jzry : jzries) {
                List<XzqhBjQueryResultDTO> bjs = xzqhBjCache.getByXzqhId(jzry.getXzqhId());
                if (ObjectUtil.isEmpty(bjs)) {
                    continue;
                }
                //只要进入了其中一个
                boolean withinArea = bjs.stream().anyMatch(bj -> DistanceUtils.isWithinArea(
                        Double.parseDouble(position.getLongitude()),
                        Double.parseDouble(position.getLatitude()),
                        bj.getBjjwd(),
                        0.d));
                if (!withinArea) {
                    continue;
                }

                adds.add(
                        BeanUtil.copyProperties(position, AbnProhibitAreasPositionAddDTO.class)
                                .setProhibitId(jzry.getId())
                                .setPositionId(position.getId())
                );
            }
        }
        abnProhibitAreasPositionService.saveAbnProhibitAreasPosition(adds);
    }

    private Map<String, List<AbnProhibitAreasWithJzryDTO>> listAbnProhibitAreasWithJzry(Set<String> jzIds) {
        List<AbnProhibitAreasWithJzryDTO> result = abnProhibitAreasCache.listAbnProhibitAreasWithJzry();
        if (ObjectUtil.isEmpty(result)) {
            return null;
        }
        return result.stream().filter(e -> jzIds.contains(e.getJzId())).collect(Collectors.groupingBy(AbnProhibitAreasWithJzryDTO::getJzId));
    }

    /**
     * 查询列表：分页
     *
     * @param dto  查询条件
     * @param page 分页信息
     * @return 对象列表
     */
    @Override
    @DictConvert
    public QueryPageResultDTO<AbnProhibitAreasQueryResultDTO> pageAbnProhibitAreas(AbnProhibitAreasQueryParamDTO dto, PageParamDTO page) {
        return this.abnProhibitAreasDao.pageAbnProhibitAreas(dto, page);
    }

    private void refresh() {
        abnProhibitAreasCache.remove();
    }
}
